package com.csthink.mr.outputformat;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.db.DBConfiguration;
import org.apache.hadoop.mapreduce.lib.db.DBOutputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import java.io.IOException;

/**
 * @author <a href="mailto:csthink@icloud.com">Mars</a>
 * @since 2024-04-15 19:34
 */
public class DBOutputFormatApp {

    public static void main(String[] args) throws Exception {

        String input = "data/account.txt";

        Configuration conf = new Configuration();
        DBConfiguration.configureDB(conf,
                "com.mysql.cj.jdbc.Driver",
                "jdbc:mysql://localhost:3306/csthink",
                "root",
                "123456");
        Job job = Job.getInstance(conf);

        job.setJarByClass(DBOutputFormatApp.class);

        job.setMapperClass(MyMapper.class);
        job.setReducerClass(MyReducer.class);
        job.setOutputFormatClass(DBOutputFormat.class);

        job.setMapOutputKeyClass(LongWritable.class);
        job.setMapOutputValueClass(Text.class);

        job.setOutputKeyClass(Account.class);
        job.setOutputValueClass(NullWritable.class);

        String[] fields = {"id", "name", "email", "is_setup", "account_options"};
        DBOutputFormat.setOutput(job, "cst_account", fields);

        FileInputFormat.setInputPaths(job, new Path(input));

        boolean result = job.waitForCompletion(true);
        System.exit(result ? 0 : 1);
    }

    public static class MyMapper extends Mapper<LongWritable, Text, LongWritable, Text> {

        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

            context.write(key, value);
        }
    }

    public static class MyReducer extends Reducer<LongWritable, Text, Account, NullWritable> {

        @Override
        protected void reduce(LongWritable key, Iterable<Text> values, Reducer<LongWritable, Text, Account, NullWritable>.Context context) throws IOException, InterruptedException {

            for (Text value : values) {
                String[] split = value.toString().split(",");
                Account account = new Account(
                        split[0].trim(),
                        split[1].trim(),
                        split[2].trim(),
                        Integer.parseInt(split[3]),
                        Long.parseLong(split[4]));
                context.write(account, NullWritable.get());
            }
        }
    }
}
